#if defined DOO_inc || defined DOO2_inc
#endinput
#endif
#define DOO_inc

#include <a_samp>

#if !defined VIEW_DISTANCE
#define VIEW_DISTANCE 250.0
#endif

#if !defined MAX_STREAM_OBJECTS
#define MAX_STREAM_OBJECTS 2000
#endif
#define ALL_WORLDS -1

#define RRR_PLAYERS 10

/*
//#define IsPosInDistance(%0,%1,%2,%3,%4,%5,%6) \
//		(((%0 - %3) * (%0 - %3)) + ((%1 - %4) * (%1 - %4)) + ((%2 - %5) * (%2 - %5)) <= (%6 * %6))// BIG THX to Goldkiller
*/

new ObjectModel[MAX_STREAM_OBJECTS];
new Float:ObjectPos[MAX_STREAM_OBJECTS][3];
new Float:ObjectRotation[MAX_STREAM_OBJECTS][3];
//new Float:ObjectDistance[MAX_STREAM_OBJECTS];
new ObjectObjectID[RRR_PLAYERS][MAX_STREAM_OBJECTS];
//new ObjectWorld[MAX_STREAM_OBJECTS];
new bool:ObjectCreated[MAX_STREAM_OBJECTS];
new bool:ObjectsStreamed[RRR_PLAYERS];
new ObjectCount[RRR_PLAYERS];

new AllObjects = 0;

#define GetStreamObjectObjectID(%0,%1) (IsValidStreamObject(%1)?(ObjectObjectID[%0][%1]):INVALID_OBJECT_ID)

#define IsValidStreamObject(%1) (((%1>=0&&%1<MAX_STREAM_OBJECTS)&&ObjectCreated[%1])?true:false)


forward CreateStreamObject(modelid, Float:X, Float:Y, Float:Z, Float:rX, Float:rY, Float:rZ);
forward DestroyStreamObject(objectid);
forward StreamObjects();
forward StreamPlayerObjects(playerid,Float:x,Float:y,Float:z);
forward StreamPlayerObject(playerid,objectid);
forward MoveStreamObject(objectid,Float:x,Float:y,Float:z,Float:speed);
forward StopStreamObject(objectid);
forward DOO_SetPlayerPos(playerid,Float:x,Float:y,Float:z);
forward DOO_SetVehiclePos(vehicleid,Float:x,Float:y,Float:z);
forward SetStreamObjectRot(objectid, Float:rX, Float:rY, Float:rZ);
forward SetStreamObjectPos(objectid, Float:x, Float:y, Float:z);
forward GetStreamObjectRot(objectid, &Float:rX, &Float:rY, &Float:rZ);
forward GetStreamObjectPos(objectid, &Float:x, &Float:y, &Float:z);
//forward SetObjectViewDistance(objectid,Float:distance);

DOO_OnGameModeInit()
{
	SetTimer("StreamObjects",3000,true);
}

DOO_OnPlayerConnect(playerid)
{
	ObjectsStreamed[playerid] = false;
	ObjectCount[playerid]=0;
	for(new i=0;i<MAX_STREAM_OBJECTS;i++)
		ObjectObjectID[playerid][i] = INVALID_OBJECT_ID;
}

DOO_OnPlayerDisconnect(playerid)
{
	for(new i=0;i<MAX_STREAM_OBJECTS;i++)
		ObjectObjectID[playerid][i] = INVALID_OBJECT_ID;

	for(new i=0;i<MAX_OBJECTS;i++)
		if(IsValidPlayerObject(playerid,i))
			DestroyPlayerObject(playerid,i);
}

public CreateStreamObject(modelid, Float:X, Float:Y, Float:Z, Float:rX, Float:rY, Float:rZ)
{
	//#pragma unused dist
	if(AllObjects >= MAX_STREAM_OBJECTS) return(INVALID_OBJECT_ID);
	for(new i=0;i<MAX_STREAM_OBJECTS;i++)
	{
		if(!ObjectCreated[i])
		{
			ObjectModel[i]=modelid;
			ObjectPos[i][0]=X;
			ObjectPos[i][1]=Y;
			ObjectPos[i][2]=Z;
			ObjectRotation[i][0]=rX;
			ObjectRotation[i][1]=rY;
			ObjectRotation[i][2]=rZ;
			//ObjectDistance[i]=distance;
			//ObjectWorld[i]=worldid;
			ObjectCreated[i]=true;
			AllObjects++;
			return i;
		} /*else if(ObjectModel[i]==modelid&&
			ObjectPos[i][0]==X&&ObjectPos[i][1]==Y&&ObjectPos[i][2]==Z&&
			ObjectRotation[i][0]==rX&&ObjectRotation[i][1]==rY&&ObjectRotation[i][2]==rZ) return i;*/
	}
	return INVALID_OBJECT_ID;
}

public DestroyStreamObject(objectid)
{
	if(IsValidStreamObject(objectid))
	{
		for(new i=0;i<RRR_PLAYERS;i++)
		{
			if(IsPlayerConnected(i) && ObjectObjectID[i][objectid]!=INVALID_OBJECT_ID)
			{
				DestroyPlayerObject(i,ObjectObjectID[i][objectid]);
				ObjectObjectID[i][objectid]=INVALID_OBJECT_ID;
				ObjectCount[i]--;
			}
		}
		ObjectCreated[objectid]=false;
		AllObjects--;
		return 1;
	}
	return 0;
}

/*
public SetObjectViewDistance(objectid,Float:distance)
{
	if(IsValidStreamObject(objectid))
	{
		ObjectDistance[objectid]=distance;
		return 1;
	}
	return 0;
}
*/
stock IsPosInDistance(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2, Float:radius)// PlayerToPoint edit
{
    x1 = (x1-x2);
    y1 = (y1-y2);
    z1 = (z1-z2);
    return(((x1 < radius) && (x1 > -radius)) && ((y1 < radius) && (y1 > -radius)) && ((z1 < radius) && (z1 > -radius)));
}

/*
public StreamObjects()
{
	new Float:x,Float:y,Float:z;
	for(new i=0;i<RRR_PLAYERS;i++)
	{
		if(GetPlayerPos(i,x,y,z))
		{
			if(ObjectsStreamed[i])
				ObjectsStreamed[i]=false;
			else
				StreamPlayerObjects(i,x,y,z);
		}
	}
	return 1;
}*/

public StreamObjects()
{
	new pstate;
	for(new j=0;j<MAX_STREAM_OBJECTS;j++)
		for(new i=0;i<RRR_PLAYERS;i++)
		{
			pstate = GetPlayerState(i);
			if(pstate == PLAYER_STATE_DRIVER || pstate == PLAYER_STATE_PASSENGER || pstate == PLAYER_STATE_ONFOOT)
			{
				if(ObjectsStreamed[i])
					ObjectsStreamed[i] = false;
				else
					StreamPlayerObject(i, j);
			}
		}
	return 1;
}

public StreamPlayerObjects(playerid,Float:x,Float:y,Float:z)
{
	for(new i=0;i<MAX_STREAM_OBJECTS;i++)
	{
		if(ObjectCreated[i])
		{
			if(IsPosInDistance(x,y,z,ObjectPos[i][0],ObjectPos[i][1],ObjectPos[i][2],VIEW_DISTANCE))
			{
				if(ObjectObjectID[playerid][i]==INVALID_OBJECT_ID && ObjectCount[playerid]<MAX_OBJECTS)
				{
					ObjectObjectID[playerid][i] = CreatePlayerObject(playerid,ObjectModel[i],ObjectPos[i][0],ObjectPos[i][1],ObjectPos[i][2],ObjectRotation[i][0],ObjectRotation[i][1],ObjectRotation[i][2]);
					ObjectCount[playerid]++;
				}
			}
			else
			{
				if(ObjectObjectID[playerid][i]!=INVALID_OBJECT_ID)
				{
					DestroyPlayerObject(playerid,ObjectObjectID[playerid][i]);
					ObjectObjectID[playerid][i] = INVALID_OBJECT_ID;
					ObjectCount[playerid]--;
				}
			}
		}
	}
	return 1;
}

public StreamPlayerObject(playerid, objectid)
{
	if(ObjectCreated[objectid] && IsPlayerConnected(playerid))
	{
		if(IsPlayerInRangeOfPoint(playerid, VIEW_DISTANCE, ObjectPos[objectid][0],ObjectPos[objectid][1],ObjectPos[objectid][2]))
		{
			if(ObjectObjectID[playerid][objectid]==INVALID_OBJECT_ID && ObjectCount[playerid]<MAX_OBJECTS)
			{
				ObjectObjectID[playerid][objectid] = CreatePlayerObject(playerid,ObjectModel[objectid],ObjectPos[objectid][0],ObjectPos[objectid][1],ObjectPos[objectid][2],ObjectRotation[objectid][0],ObjectRotation[objectid][1],ObjectRotation[objectid][2]);
				ObjectCount[playerid]++;
			}
		}
		else
		{
			if(ObjectObjectID[playerid][objectid]!=INVALID_OBJECT_ID)
			{
				DestroyPlayerObject(playerid,ObjectObjectID[playerid][objectid]);
				ObjectObjectID[playerid][objectid] = INVALID_OBJECT_ID;
				ObjectCount[playerid]--;
			}
		}
		return true;
	}
	return false;
}

/*
stock IsValidStreamObject(objectid)
{
	if(objectid>=0 && objectid<MAX_STREAM_OBJECTS)
		if(ObjectCreated[objectid])
			return true;
	return false;
}*/

public MoveStreamObject(objectid,Float:x,Float:y,Float:z,Float:speed)
{
	if(IsValidStreamObject(objectid))
	{
		for(new i=0;i<RRR_PLAYERS;i++)
			if(IsPlayerConnected(i) && ObjectObjectID[i][objectid]!=INVALID_OBJECT_ID)
				MovePlayerObject(i,ObjectObjectID[i][objectid],x,y,z,speed);
		ObjectPos[objectid][0]=x;
		ObjectPos[objectid][1]=y;
		ObjectPos[objectid][2]=z;
		return 1;
	}
	return 0;
}

public SetStreamObjectPos(objectid, Float:x, Float:y, Float:z)
{
	if(IsValidStreamObject(objectid))
	{
		for(new i=0;i<MAX_PLAYERS;i++)
			if(IsPlayerConnected(i) && ObjectObjectID[i][objectid]!=INVALID_OBJECT_ID)
				SetPlayerObjectPos(i, ObjectObjectID[i][objectid], x, y, z);
		ObjectPos[objectid][0]=x;
		ObjectPos[objectid][1]=y;
		ObjectPos[objectid][2]=z;
		return 1;
	}
	return 0;
}

public SetStreamObjectRot(objectid, Float:rX, Float:rY, Float:rZ)//SetPlayerObjectRot futsch => Funktioniert nicht!
{
	if(IsValidStreamObject(objectid))
	{
		for(new i=0;i<RRR_PLAYERS;i++)
			if(IsPlayerConnected(i) && ObjectObjectID[i][objectid]!=INVALID_OBJECT_ID)
				SetPlayerObjectRot(i, ObjectObjectID[i][objectid], rX, rY, rZ);
		ObjectRotation[objectid][0]=rX;
		ObjectRotation[objectid][1]=rY;
		ObjectRotation[objectid][2]=rZ;
		return 1;
	}
	return 0;
}
public StopStreamObject(objectid)
{
	if(IsValidStreamObject(objectid))
	{
		for(new i=0;i<RRR_PLAYERS;i++)
			if(IsPlayerConnected(i) && ObjectObjectID[i][objectid]!=INVALID_OBJECT_ID)
				StopPlayerObject(i,ObjectObjectID[i][objectid]);
		return 1;
	}
	return 0;
}

public GetStreamObjectRot(objectid, &Float:rX, &Float:rY, &Float:rZ)
{
	if(IsValidStreamObject(objectid))
	{
		rX = ObjectRotation[objectid][0];
		rY = ObjectRotation[objectid][1];
		rZ = ObjectRotation[objectid][2];
		return 1;
	}
	return 0;
}

public GetStreamObjectPos(objectid, &Float:x, &Float:y, &Float:z)
{
	if(IsValidStreamObject(objectid))
	{
		x = ObjectPos[objectid][0];
		y = ObjectPos[objectid][1];
		z = ObjectPos[objectid][2];
		return 1;
	}
	return 0;
}

public DOO_SetPlayerPos(playerid,Float:x,Float:y,Float:z)
{
	if(IsPlayerConnected(playerid))
	{
		ObjectsStreamed[playerid] = true;
		StreamPlayerObjects(playerid,x,y,z);
		#if defined af_fix_inc
		af_ClearPlayerVehicle(playerid);
		#endif
		#if defined _streamer_included
		Streamer_UpdateEx(playerid,x,y,z);
		#endif
		return SetPlayerPos(playerid,x,y,z);
	}
	return 0;
}

public DOO_SetVehiclePos(vehicleid,Float:x,Float:y,Float:z)
{
	for(new i=0;i<RRR_PLAYERS;i++)
	{
		if(IsPlayerInVehicle(i,vehicleid))
		{
			ObjectsStreamed[i] = true;
			StreamPlayerObjects(i,x,y,z);
		}
	}
	return SetVehiclePos(vehicleid,x,y,z);
}

